export default class HashTable {
    private storage = [];
    private count = 0;
    private limit = 7;
    public hashFunc(str: string, size: number): number {
      var hashCode = 0;
      for (var i = 0; i < str.length; i++) {
        hashCode = 37 * hashCode + str.charCodeAt(i);
      }
      return hashCode % size;
    }
    public put(key: string, value: any): void {
      var index = this.hashFunc(key, this.limit);
      var bucket = this.storage[index];
      // 初始化
      if (bucket) {
        bucket.forEach((item) => {
          if (item[0] === key) {
            item[1] = value;
          }
        });
      } else {
        bucket = [];
        bucket.push([key, value]);
        this.storage[index] = bucket;
        this.count += 1;
        // 判断是否需要扩容
        this.isNeedResize();
      }
    }
    public get(key: string): any {
      var index = this.hashFunc(key, this.limit);
      var bucket = this.storage[index];
      var value: any = "";
      if (bucket) {
        bucket.forEach((item) => {
          if (item[0] === key) {
            value = item[1];
          }
        });
      } else {
        return null;
      }
      return value;
    }
    public remove(key: string): any {
      var index = this.hashFunc(key, this.limit);
      var bucket = this.storage[index];
      var value: any = "";
      // 初始化
      if (bucket) {
        bucket.forEach((item, i) => {
          if (item[0] === key) {
            value = item[1];
            bucket.splice(i, 1);
            this.count -= 1;
            // 判断是否需要扩容
            this.isNeedResize();
          }
        });
      } else {
        return null;
      }
      return value;
    }
    public isEmpty(): boolean {
      return !this.count;
    }
    public size(): number {
      return this.count;
    }
    public toString(): string {
      var arr: string[] = [];
      this.storage.forEach((item) => {
        item.forEach((ele) => {
          arr.push(`${ele[0]}:${ele[1]}`);
        });
      });
      return arr.join(",");
    }
    // 扩容
    public resize(limit: number): void {
      var oldStorage = this.storage;
      this.count = 0;
      this.limit = limit;
      this.storage = [];
      oldStorage.forEach((item) => {
        item.forEach((ele) => {
          this.put(ele[0], ele[1]);
        });
      });
    }
    // 判断是否需要改变容量
    private isNeedResize() {
      if (this.count > this.limit * 0.75) {
        this.resize(this.getPrimeNum(this.limit * 2));
      } else if (this.limit > 7 && this.count < this.limit * 0.25) {
        this.resize(this.getPrimeNum(Math.floor(this.limit / 2)));
      }
    }
    // 判断是否是质数 只能被1和自己整除
    public isPrimeNumber(num: number): boolean {
      var tmpNum = parseInt(Math.sqrt(num));
      for (var i = 2; i <= tmpNum; i++) {
        if (num % i === 0) return false;
      }
      return true;
    }
    // 转为质数
    public getPrimeNum(num: number): number {
      while (!this.isPrimeNumber(num)) {
        num += 1;
      }
      return num;
    }
  }

